home *** CD-ROM | disk | FTP | other *** search
/ Risc World 3 / Risc World 3.iso / SOFTWARE / ISSUE6 / PD / PDF / pdf / c++ / DocView < prev    next >
Text File  |  2003-02-24  |  28KB  |  934 lines

  1. //--------------------------------------------------------------------------
  2. //
  3. //   Copyright (c) 2002, Colin Granville
  4. //
  5. //   All rights reserved.
  6. //
  7. //   Redistribution and use in source and binary forms, with or
  8. //   without modification, are permitted provided that the following 
  9. //   conditions are met:
  10. //
  11. //      * Redistributions of source code must retain the above copyright 
  12. //        notice, this list of conditions and the following disclaimer.
  13. //
  14. //      * Redistributions in binary form must reproduce the above 
  15. //        copyright notice, this list of conditions and the following 
  16. //        disclaimer in the documentation and/or other materials 
  17. //        provided with the distribution.
  18. //
  19. //      * The name Colin Granville may not be used to endorse or promote 
  20. //        products derived from this software without specific prior 
  21. //        written permission.
  22. //
  23. //   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  24. //   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
  25. //   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
  26. //   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
  27. //   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
  28. //   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
  29. //   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  30. //   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  31. //   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  32. //   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  33. //   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
  34. //   OF THE POSSIBILITY OF SUCH DAMAGE.
  35. //
  36. //--------------------------------------------------------------------------
  37.  
  38. #include "DocView.h"
  39. #include "Document.h"
  40. #include "GuiHourglass.h"
  41. #include "UserEvents.h"
  42. #include "GuiScale.h"
  43. #include "PrintDialog.h"
  44. #include "pointer.h"
  45. #include "GuiTask.h"
  46. #include "UriDispatch.h"
  47. #include "gfile.h"
  48. #include "guilib:gfx.h"
  49. #include "Find.h"
  50. #include "outline.h"
  51.  
  52. //*************************************************************************
  53.  
  54. void DragWorkArea::drag(GuiWindow& win)
  55. {
  56.   window = &win;
  57.   GuiPointerInfo info;
  58.  
  59.   GuiGetWindowStateBlock ws;
  60.   win.getState(ws);
  61.  
  62.   x=info.x;
  63.   y=info.y;
  64.  
  65.   GuiBBox box;
  66.   win.getExtent(box);
  67.   GuiBBox extent=ws.toScreen(box);
  68.  
  69.   GuiDragBox db;
  70.   db.parentBox.xmin = x-extent.xmax+ws.visibleArea.xmax;
  71.   db.parentBox.xmax = x+ws.visibleArea.xmin-extent.xmin;
  72.   db.parentBox.ymax = y+ws.visibleArea.ymin-extent.ymin;
  73.   db.parentBox.ymin = y-extent.ymax+ws.visibleArea.ymax;
  74.   
  75.   db.startDrag(GuiDragBox::DragPoint);
  76.   dragEndedTarget(0,GuiWimp_EUserDrag,this,DragWorkArea::dragEnded);
  77.   nullEventTarget(this,DragWorkArea::nullEvent);
  78. }
  79.  
  80. //*************************************************************************
  81.  
  82. void DragWorkArea::nullEvent()
  83. {
  84.   GuiPointerInfo info;
  85.  
  86.   GuiGetWindowStateBlock ws;
  87.   window->getState(ws);
  88.  
  89.   if (info.x==x && info.y==y) return;
  90.   
  91.   ws.yscroll+=(y-info.y);
  92.   ws.xscroll+=(x-info.x);
  93.  
  94.   window->show(ws);
  95.  
  96.   x=info.x;
  97.   y=info.y;
  98.  
  99. }
  100.  
  101. //*************************************************************************
  102.  
  103. Claim DragWorkArea::dragEnded(GuiWimpPollBlock&,const GuiIdBlock&)
  104. {
  105.   nullEventTarget.destroy();
  106.   dragEndedTarget.destroy();
  107.   return CLAIM;
  108. }
  109.  
  110. //*************************************************************************
  111. //*************************************************************************
  112. //*************************************************************************
  113.  
  114. //DEFINE_RTTI_DERIVED(View,Node);
  115. DEFINE_RTTI_DERIVED(DocView,Node);
  116.  
  117. DocView::DocView(Document& doc,const DocViewChoices& choices,int page, int logicalPageOffset)
  118.  : document(0),
  119.    mainWin("mainWin"),
  120.    displayMenu("displayMenu"),
  121.    toolbar(*this,mainWin),
  122.    save(*this,mainWin),
  123.    handPointerShowing(0),
  124.    highlightIsOn(0),
  125.    closeWindowTarget(&mainWin,GuiWimp_ECloseWindow,this,DocView::closeWindow),
  126.    openWindowTarget(&mainWin,GuiWimp_EOpenWindow,this,DocView::openWindow),
  127.    redrawWindowTarget(&mainWin,GuiWimp_ERedrawWindow,this,DocView::redrawWindow),
  128.    mouseClickTarget(&mainWin,GuiWimp_EMouseClick,this,DocView::mouseClick),
  129.    pointerEnteringTarget(&mainWin,GuiWimp_EPointerEnteringWindow,this,DocView::pointerEntering),
  130.    pointerLeavingTarget(&mainWin,GuiWimp_EPointerLeavingWindow,this,DocView::pointerLeaving),
  131.    newViewTarget(&mainWin,User_NewView,this,DocView::newView),
  132.    rotateViewTarget(&mainWin,User_RotateView,this,DocView::rotateView),
  133.    printDialogOpenTarget(&mainWin,User_PrintDialogOpen,this,DocView::printDialogOpen),
  134.    displayMenuATBSTarget(&mainWin,User_DisplayMenuATBS,this,DocView::displayMenuATBS),
  135.    miscMenuATBSTarget(&mainWin,User_MiscMenuATBS,this,DocView::miscMenuATBS),
  136.    saveMenuATBSTarget(&mainWin,User_SaveMenuATBS,this,DocView::saveMenuATBS),
  137.    highlightLinksTarget(&mainWin,User_HighlightLinks,this,DocView::highlightLinks),
  138.    setNoImagesTarget(&mainWin,User_SetNoImages,this,DocView::setNoImages),
  139.    setNoTextTarget(&mainWin,User_SetNoText,this,DocView::setNoText),
  140.    setNoType3FontsTarget(&mainWin,User_SetNoType3Fonts,this,DocView::setNoType3Fonts),
  141.    setNoDrawingsTarget(&mainWin,User_SetNoDrawings,this,DocView::setNoDrawings),
  142.    fileInfoATBSTarget(&mainWin,User_FileInfoATBS,this,DocView::fileInfoATBS),
  143.    scaleViewTarget(&mainWin,GuiScale::ApplyFactor::Event,this,DocView::scaleView),
  144.    scaleUpTarget(&mainWin,User_ScaleUp,this,DocView::scaleUp),
  145.    scaleDownTarget(&mainWin,User_ScaleDown,this,DocView::scaleDown),
  146.    scale100Target(&mainWin,User_Scale100,this,DocView::scale100),
  147.    scaleATBSTarget(&mainWin,GuiScale::AboutToBeShown::Event,this,DocView::scaleATBS),
  148.    saveDisplayChoicesTarget(&mainWin,User_SaveDisplayChoices,this,DocView::saveDisplayChoices),
  149.    findATBSTarget(&mainWin,User_FindATBS,this,DocView::findATBS)
  150. {
  151.   set(doc,choices,page,logicalPageOffset);
  152. }
  153.  
  154.  
  155. DocView::~DocView() 
  156. {
  157.   find(*this,FIND_VIEW_CLOSED);
  158.   if (getParent()) getParent()->removeChild(this);
  159. }
  160.  
  161. //*************************************************************************
  162.  
  163. void DocView::set(Document& doc,const DocViewChoices& new_choices,
  164.                  int page,int logicalPageOffset,bool add_to_history)
  165.  
  166.   toolbar.flushPendingHistory();
  167.   if (&doc!=document)
  168.   {
  169.     if (document && document!=&doc)
  170.     {
  171.        highlightIsOn=0;
  172.        find(*this,FIND_VIEW_CLOSED);
  173.        document->removeChild(this);
  174.     }
  175.    
  176.     document=&doc;
  177.     document->addChild(this);
  178.   }
  179.   toolbar.setFirstPage(page,logicalPageOffset,document->getPageCount(),add_to_history);
  180.   if (&choices != &new_choices) choices=new_choices;
  181.   showPage();
  182.   scroll(SCROLL_TOP);
  183. }
  184.  
  185. //*************************************************************************
  186.  
  187. void DocView::setPage(const DocPage& page,bool add_to_history)
  188.   Document* new_doc=makeDocument(*document->getParent(),page.docName.c_str());
  189.   if (new_doc) set(*new_doc,choices,page.page,toolbar.getLogicalPageOffset(),add_to_history);
  190. }
  191.  
  192. //*************************************************************************
  193.  
  194. void DocView::transformHighlight(GuiBBox& box)
  195. {
  196.   double factor=((double)choices.getScale())/25600.0; //scale and convert to os units
  197.   box.xmin=(int)(highlightArea.xmin*factor);
  198.   box.ymin=(int)(highlightArea.ymin*factor);
  199.   box.xmax=(int)(highlightArea.xmax*factor);
  200.   box.ymax=(int)(highlightArea.ymax*factor);
  201.  
  202.   if (choices.getRotation()!=0)
  203.   {
  204.     GuiBBox paper;
  205.     mainWin.getExtent(paper);
  206.     GuiBBox toolbarBox;
  207.     toolbar.getExtent(toolbarBox);
  208.     paper.ymax-=toolbarBox.getHeight();
  209.  
  210.     int x,y,wid,ht;
  211.     switch (choices.getRotation())
  212.     {
  213.       case 180:
  214.         wid = box.getWidth();
  215.         ht  = box.getHeight();
  216.         x=paper.getWidth()-(box.xmin+box.xmax)/2;
  217.         y=paper.getHeight()-2-(box.ymin+box.ymax)/2;
  218.         break;
  219.       case 270:
  220.         wid = box.getHeight();
  221.         ht  = box.getWidth();
  222.         y=-2+(box.xmin+box.xmax)/2;
  223.         x=paper.getWidth()-(box.ymin+box.ymax)/2;
  224.         break;
  225.       default:
  226.         wid = box.getHeight();
  227.         ht  = box.getWidth();
  228.         y=-2+paper.getHeight()-(box.xmin+box.xmax)/2;
  229.         x=(box.ymin+box.ymax)/2;
  230.     }
  231.     box.xmax=x+wid/2;
  232.     box.ymax=y+ht/2;
  233.     box.xmin=box.xmax-wid;
  234.     box.ymin=box.ymax-ht;
  235.   }
  236. }
  237.  
  238. //*************************************************************************
  239.  
  240. void DocView::setHighlight(int pageNum,HighlightBBox& box)
  241.   bool changedPage=(pageNum!=toolbar.getPage());
  242.   if (!changedPage) clearHighlight();
  243.   highlightArea=box;
  244.   highlightIsOn=1;
  245.   if (changedPage) toolbar.setPage(pageNum);
  246.  
  247.   GuiBBox highlight;
  248.   transformHighlight(highlight);
  249.   
  250.   GuiGetWindowStateBlock ws;
  251.   mainWin.getState(ws);
  252.   GuiBBox visibleArea=ws.toWorkarea(ws.visibleArea);
  253.   
  254.   int xscroll=0;
  255.   int yscroll=0;
  256.   int d=32;
  257.   int topd=96;
  258.  
  259.   if (highlight.xmin<visibleArea.xmin)
  260.       xscroll=highlight.xmin-visibleArea.xmin-d;
  261.   else if (highlight.xmax>visibleArea.xmax)
  262.       xscroll= highlight.xmax-visibleArea.xmax+d;
  263.  
  264.   if ( (xscroll || changedPage) && highlight.xmax < visibleArea.getWidth())
  265.       xscroll=-visibleArea.xmin;
  266.  
  267.   if (highlight.ymin<visibleArea.ymin)
  268.       yscroll=highlight.ymin-visibleArea.ymin-d;
  269.   else if (highlight.ymax>visibleArea.ymax-topd)
  270.       yscroll=highlight.ymax-visibleArea.ymax+topd;
  271.  
  272.   if (xscroll!=0 || yscroll!=0)
  273.   {
  274.     ws.xscroll+=xscroll;
  275.     ws.yscroll+=yscroll;
  276.     mainWin.show(ws);
  277.   }
  278.   if (!changedPage)
  279.   {
  280.     highlight.xmax+=4;
  281.     highlight.ymax+=4;
  282.     mainWin.forceRedraw(highlight);
  283.   }
  284. }
  285.  
  286. //*************************************************************************
  287.  
  288. void DocView::clearHighlight()
  289. {
  290.   if (highlightIsOn)
  291.   {
  292.     GuiBBox highlight;
  293.     transformHighlight(highlight);
  294.     highlight.xmax+=4;
  295.     highlight.ymax+=4;
  296.     mainWin.forceRedraw(highlight);
  297.     highlightIsOn=0;
  298.   }
  299. }
  300.  
  301. //*************************************************************************
  302.  
  303. void DocView::showPage()
  304. {
  305.   GuiHourglass hg;
  306.   outDev.setNoImages(choices.getNoImages());
  307.   outDev.setNoText(choices.getNoText());
  308.   outDev.setNoType3Fonts(choices.getNoType3Fonts());
  309.   outDev.setNoDrawings(choices.getNoDrawings());
  310.   document->getPage(toolbar.getPage(),&outDev,DrawOutputDevice::DPI,choices.getRotation());
  311.   Scale(Scale());
  312.   links.reset(document->makeLinks(toolbar.getPage()));
  313.   nullEvent();
  314. }
  315.  
  316. //*************************************************************************
  317.  
  318. void DocView::Redraw(int)
  319. {
  320.   GuiBBox box;
  321.   mainWin.getExtent(box);
  322.   mainWin.forceRedraw(box);
  323. }
  324.  
  325. //*************************************************************************
  326.  
  327. void DocView::Scale(int percent)
  328. {
  329.   static int off=3;
  330.  
  331.    choices.setScale(percent);
  332.    GuiTransform trfm;
  333.    trfm.m0 = (percent << 16) / 100; trfm.m1 = 0;
  334.    trfm.m2 = 0;                     trfm.m3 = trfm.m0;
  335.    trfm.m4 = 0;                     trfm.m5 = 0;
  336.  
  337.    GuiBBox bounds;
  338.    outDev.getDrawFile().getBBox(bounds,&trfm);
  339.    if (bounds.getWidth() < 640*256)
  340.    {
  341.      //scale to minimum width
  342.      int wid = bounds.getWidth();
  343.      if (wid<80*256) wid=80*256;
  344.      choices.setScale(((percent*640*256)/wid)+1);
  345.      trfm.m0 = (Scale() << 16) / 100;
  346.      trfm.m3 = trfm.m0;
  347.      outDev.getDrawFile().getBBox(bounds,&trfm);
  348.    }
  349.  
  350.    GuiBBox ex;
  351.    ex(0,0,bounds.xmax/256,bounds.ymax/256);
  352.  
  353.  
  354.    {
  355.      GuiBBox box;
  356.      toolbar.getExtent(box);
  357.      ex.ymax+=box.getHeight();
  358.    }
  359.  
  360.    mainWin.setExtent(ex);
  361.  
  362.    if (!mainWin.isShowing())
  363.    {
  364.      mainWin.showCentred(-off*36,off*36);
  365.      if (--off<0) off=3;
  366.    }
  367.    else
  368.    {
  369.      mainWin.forceRedraw(ex);
  370.    }
  371.  
  372.    GuiGetWindowStateBlock ws;
  373.    mainWin.getState(ws);
  374. //   ws.yscroll=ex.ymax;
  375.    openWindow((GuiWimpPollBlock&)ws,guiTask().idBlock());
  376. }
  377.  
  378. //*************************************************************************
  379.  
  380. int DocView::Scale()
  381. {
  382.   return choices.getScale();
  383. }
  384.  
  385. //*************************************************************************
  386.  
  387. bool DocView::scroll(ScrollType mode)
  388. {
  389.   GuiGetWindowStateBlock state;
  390.   toolbar.getState(state);
  391.   int distance=-state.visibleArea.getHeight()-32;
  392.  
  393.   mainWin.getState(state);
  394.   distance += state.visibleArea.getHeight();
  395.  
  396.   int yscroll=state.yscroll;
  397.   state.yscroll+=(mode==SCROLL_DOWN? -distance: distance);
  398.   if (mode==SCROLL_BOTTOM || mode==SCROLL_TOP)
  399.   {
  400.     GuiBBox box;
  401.     mainWin.getExtent(box);
  402.     if (mode==SCROLL_BOTTOM) state.yscroll=box.ymin;
  403.     if (mode==SCROLL_TOP) state.yscroll=box.ymax;
  404.   }
  405.   mainWin.show(state);
  406.   mainWin.getState(state);
  407.   return yscroll!=state.yscroll;
  408. }
  409.  
  410. //*************************************************************************
  411. Claim DocView::closeWindow(GuiWimpPollBlock&,const GuiIdBlock&)
  412. {
  413.   GuiPointerInfo info;
  414.   if (info.buttons & GuiPointerInfo::Adjust)
  415.   {
  416.     int shift=gfx::inkey(-1);
  417.     size_t n=document->getFileName().rfind('.');
  418.     if (n!=string::npos)
  419.     {
  420.       string s="filer_opendir ";
  421.       s+=document->getFileName().substr(0,n);
  422.       _swix(OS_CLI,_IN(0),s.c_str());
  423.       if (shift) return CLAIM;
  424.     }
  425.   }
  426.   delete this;
  427.   return CLAIM;
  428. };
  429.  
  430. //*************************************************************************
  431.  
  432. Claim DocView::openWindow(GuiWimpPollBlock& wpb,const GuiIdBlock&)
  433. {
  434.   GuiOpenWindowBlock& block=wpb.openWindowRequest;
  435.   int behind=block.behind;
  436.   block.behind=block.windowHandle;
  437.   mainWin.show(block);
  438.   mainWin.getState(block);
  439.   if (behind!=-1 && block.behind==-1) behind=-1;
  440.   block.behind=behind;
  441.   toolbar.openWindow(mainWin,block);
  442.   mainWin.show(block);
  443.   return CLAIM;
  444. };
  445.  
  446. //*************************************************************************
  447.  
  448. Claim DocView::redrawWindow(GuiWimpPollBlock& wpb,const GuiIdBlock&)
  449. {
  450.   static int fontBlend=2;
  451.   if (fontBlend==2)
  452.   {
  453.     fontBlend=(getenv("PDF$NoFontBlending")==0);
  454.   }
  455.  
  456.   bool more;
  457.   GuiRedrawWindowBlock& block=wpb.redrawWindowRequest;
  458.  
  459.   GuiTransform trfm;
  460.   trfm.m0 = (choices.getScale() << 16) / 100;  trfm.m1 = 0;
  461.   trfm.m2 = 0;                           trfm.m3 = trfm.m0;
  462.   
  463.   GuiBBox highlight;
  464.  
  465.   if (highlightIsOn) transformHighlight(highlight);
  466.  
  467.   for (GuiWindow::redraw(block,more);more;GuiWindow::getRectangle(block,more))
  468.   {
  469.     trfm.m4 = block.xToScreen(0)*256;
  470.     trfm.m5 = block.yToScreen(0)*256+128;
  471.     outDev.getDrawFile().render(&trfm,&block.redrawArea,fontBlend);
  472.  
  473.     if (fontBlend && choices.getHighlightLinks() && links.get())
  474.     {
  475.        // highlight links if drawing to screen
  476.        // use fontBlend to tell if it is to screen as
  477.        // font blending only works on the screen
  478.  
  479.        double xa1,ya1,xa2,ya2,width;
  480.        int x1,y1,x2,y2;
  481.        int i;
  482.        for (i=0;i<links->getNumLinks();i++)
  483.        {
  484.          Link* link=links->getLink(i);
  485.          if (!link) continue;
  486.          link->getBorder(&xa1,&ya1,&xa2,&ya2,&width);
  487.          outDev.cvtUserToDev(xa1,ya1,&x1,&y1);
  488.          outDev.cvtUserToDev(xa2,ya2,&x2,&y2);
  489.          x1=(x1*choices.getScale())/25600;
  490.          y1=(y1*choices.getScale())/25600;
  491.          x2=(x2*choices.getScale())/25600;
  492.          y2=(y2*choices.getScale())/25600;
  493.          if (x2<x1) {int temp=x1;x1=x2;x2=temp;}
  494.          if (y2<y1) {int temp=y1;y1=y2;y2=temp;}
  495.          gfx::gcol_bgr(1,0xb0000000);
  496.          gfx::rectanglefill(block.xToScreen(x1),block.yToScreen(y1),x2-x1,y2-y1);
  497.        }
  498.     }
  499.  
  500.     if (highlightIsOn)
  501.     {
  502.       int x=trfm.m4/256;
  503.       int y=trfm.m5/256;
  504.       gfx::move(x+highlight.xmin,y+highlight.ymin);
  505.       gfx::plot(gfx::RectangleFill | gfx::DrawAbsInverse,
  506.                 x+highlight.xmax,y+highlight.ymax);
  507.     }
  508.   }
  509.   return CLAIM;
  510. }
  511.  
  512. //*************************************************************************
  513.  
  514. Claim DocView::mouseClick(GuiWimpPollBlock& wpb,const GuiIdBlock&)
  515. {
  516.   if ((wpb.mouseClick.buttons & GuiPointerInfo::Menu) == 0)toolbar.setFocus();
  517.   if (!links.get() || (wpb.mouseClick.buttons & GuiPointerInfo::Menu)) return CLAIM;
  518.  
  519.   GuiGetWindowStateBlock ws;
  520.   mainWin.getState(ws);
  521.   int x=ws.xToWorkarea(wpb.mouseClick.x)*256;
  522.   int y=ws.yToWorkarea(wpb.mouseClick.y)*256;
  523.   
  524.   x=(x*100)/choices.getScale();
  525.   y=(y*100)/choices.getScale();
  526.   double user_x,user_y;
  527.   outDev.cvtDevToUser(x,y,&user_x,&user_y);
  528.   LinkAction* action=links->find(user_x,user_y);
  529.   if (action==0)
  530.   {
  531.     dragView.drag(mainWin);
  532.     return CLAIM;
  533.   }
  534.  
  535.   doAction(action,wpb.mouseClick.buttons & GuiPointerInfo::Adjust);
  536.   return CLAIM;
  537. }
  538.  
  539. //*************************************************************************
  540.  
  541. void DocView::doAction(LinkAction* action,bool adjust)
  542. {
  543.   switch (action->getKind())
  544.   {
  545.     case actionGoTo:
  546.          {
  547.            LinkGoTo& go = *(LinkGoTo*)action;
  548.            LinkDest* dest=go.getDest();
  549.            if (!dest) dest=document->findDest(go.getNamedDest());
  550.            if (!dest || !dest->isOk()) break;
  551.            int page=dest->getPageNum();
  552.            if (dest->isPageRef()) page=document->findPage(dest->getPageRef());
  553.            if (adjust)
  554.               makeDocView(document,choices,page,toolbar.getLogicalPageOffset());
  555.            else
  556.               set(*document,choices,page,toolbar.getLogicalPageOffset());
  557.            break;
  558.          }
  559.     case actionGoToR:
  560.          {
  561.            LinkGoToR& go = *(LinkGoToR*)action;
  562.  
  563.            char* s = go.getFileName()->getCString();
  564.            auto_ptr<GString> file_name;
  565.            if (isAbsolutePath(s)) 
  566.              file_name.reset(new GString(s));
  567.            else 
  568.              file_name.reset(appendToPath(grabPath((char*)document->getFileName().c_str()), s));
  569.            if (!file_name.get()) break;
  570.  
  571.            int page=0;
  572.            LinkDest* dest=go.getDest();
  573.            if (dest && dest->isOk())
  574.            {
  575.              page=dest->getPageNum();
  576.              if (dest->isPageRef()) page=document->findPage(dest->getPageRef());
  577.            }
  578.  
  579.            Document* new_doc=makeDocument(*document->getParent(),file_name->getCString());
  580.            if (!new_doc) break;
  581.  
  582.            if (!dest)
  583.            {
  584.              dest=new_doc->findDest(go.getNamedDest());
  585.              if (dest && dest->isOk())
  586.              {
  587.                 page=dest->getPageNum();
  588.                 if (dest->isPageRef()) page=new_doc->findPage(dest->getPageRef());
  589.              }
  590.            }
  591.  
  592.            if (adjust)
  593.               makeDocView(new_doc,choices,page);
  594.            else
  595.               set(*new_doc,choices,page);
  596.  
  597.            break;
  598.          }
  599.     case actionURI:
  600.          {
  601.            string uri= ((LinkURI*)action)->getURI()->getCString();
  602.            dispatch_uri(uri);
  603.            break;
  604.          }
  605.     case actionLaunch:
  606.          {
  607.            char* s = ((LinkLaunch*)action)->getFileName()->getCString();
  608.            char* ext = s+((LinkLaunch*)action)->getFileName()->getLength()-4;
  609.            if (!( ext>s && (strcmp(ext, ".pdf") || strcmp(ext, ".PDF")))) break;
  610.            
  611.            auto_ptr<GString> file_name;
  612.            if (isAbsolutePath(s)) 
  613.              file_name.reset(new GString(s));
  614.            else 
  615.              file_name.reset(appendToPath(grabPath((char*)document->getFileName().c_str()), s));
  616.            if (!file_name.get()) break;
  617.  
  618.            Document* new_doc=makeDocument(*document->getParent(),file_name->getCString());
  619.            if (!new_doc) break;
  620.  
  621.            if (adjust)
  622.               makeDocView(new_doc,choices,1);
  623.            else
  624.               set(*new_doc,choices,1);
  625.            break;
  626.          }
  627.     case actionNamed:
  628.          {
  629.            GString* name = ((LinkNamed*)action)->getName();
  630.            int page=0;
  631.            if (name->cmp("NextPage")==0)       {if (getPage()<document->getPageCount()) page=getPage()+1;}
  632.            else if (name->cmp("PrevPage")==0)  page=getPage()-1;
  633.            else if (name->cmp("FirstPage")==0) page=1;
  634.            else if (name->cmp("LastPage")==0)  page=document->getPageCount();
  635.            else if (name->cmp("GoBack")==0)
  636.            {
  637.              toolbar.goBack();
  638.            }
  639.            else if (name->cmp("ShowHideBookmarks")==0)
  640.            {
  641.               Outline* o=getDocument().getOutline();
  642.               if (o) o->open(*this);
  643.            }
  644.            else if (name->cmp("Find")==0 || name->cmp("FindAgain")==0)
  645.            {
  646.              GuiWindow f("Find");
  647.              f.showCentred(0,0,&mainWin,&mainWin);
  648.            }
  649.            else if (name->cmp("Print")==0)
  650.            {
  651.              if (document->getPDFDoc().okToPrint()) PrintDialog_open(*this,mainWin,toolbar.getPage());
  652.            }
  653.  
  654.            if (page)
  655.            {
  656.              if (adjust)
  657.                  makeDocView(document,choices,page);
  658.              else
  659.                  set(*document,choices,page);
  660.            }
  661.            break;
  662.          }
  663.     case actionUnknown: break; 
  664.   }
  665. }
  666.  
  667. //*************************************************************************
  668.  
  669. void DocView::setHandPointer(bool hand)
  670. {
  671.   if (hand)
  672.   {
  673.      if (!handPointerShowing) setPointer("ptr_hand",6,0,guiTask().spriteArea());
  674.      handPointerShowing=1;
  675.   }
  676.   else
  677.   {
  678.      if (handPointerShowing) setPointer("ptr_default");
  679.      handPointerShowing=0;
  680.   }
  681. }
  682.  
  683. //*************************************************************************
  684.  
  685. Claim DocView::pointerEntering(GuiWimpPollBlock&,const GuiIdBlock&)
  686. {
  687.   nullEventTarget(this,DocView::nullEvent,25);
  688.   return CLAIM;
  689. }
  690.  
  691. //*************************************************************************
  692.  
  693. Claim DocView::pointerLeaving(GuiWimpPollBlock&,const GuiIdBlock&)
  694. {
  695.   nullEventTarget.destroy();
  696.   setHandPointer(0);
  697.   return CLAIM;
  698. }
  699.  
  700. //*************************************************************************
  701.  
  702. void DocView::nullEvent()
  703. {
  704.   if (!links.get())
  705.   {
  706.     setHandPointer(0);
  707.     return;
  708.   }
  709.   GuiPointerInfo info;
  710.   GuiGetWindowStateBlock ws;
  711.   mainWin.getState(ws);
  712.   if (info.windowHandle!=ws.windowHandle) return; //necessary because nullEvent is called on page change
  713.  
  714.   int x=ws.xToWorkarea(info.x)*256;
  715.   int y=ws.yToWorkarea(info.y)*256;;
  716.   
  717.   x=(x*100)/choices.getScale();
  718.   y=(y*100)/choices.getScale();
  719.   double user_x,user_y;
  720.   outDev.cvtDevToUser(x,y,&user_x,&user_y);
  721.   setHandPointer(links->find(user_x,user_y) != 0);
  722. }
  723.  
  724. //*************************************************************************
  725.  
  726. Claim DocView::newView(GuiToolboxEvent&,const GuiIdBlock&)
  727. {
  728.   makeDocView(document,choices,toolbar.getPage(),toolbar.getLogicalPageOffset());
  729.   return CLAIM;
  730. }
  731.  
  732. //*************************************************************************
  733.  
  734. Claim DocView::rotateView(GuiToolboxEvent&,const GuiIdBlock& id_block)
  735. {
  736.   int rot=choices.getRotation();
  737.   switch (id_block.self.component)
  738.   {
  739.     case 0: rot=0;break;
  740.     case 1: rot=270;break;
  741.     case 2: rot=180;break;
  742.     case 3: rot=90;break;
  743.   }
  744.   if (choices.getRotation()!=rot)
  745.   {
  746.     choices.setRotation(rot);
  747.     showPage();
  748.   }
  749.   return CLAIM;
  750. }
  751.  
  752.  
  753. //*************************************************************************
  754.  
  755. Claim DocView::printDialogOpen(GuiToolboxEvent&,const GuiIdBlock&)
  756. {
  757.   if (document->getPDFDoc().okToPrint()) PrintDialog_open(*this,mainWin,toolbar.getPage());
  758.   return CLAIM;
  759. }
  760.  
  761. //*************************************************************************
  762.  
  763. Claim DocView::displayMenuATBS(GuiToolboxEvent&,const GuiIdBlock&)
  764. {
  765.   displayMenu.entryTick(2,choices.getHighlightLinks()); 
  766.   displayMenu.entryTick(3,choices.getNoImages()); 
  767.   displayMenu.entryTick(5,choices.getNoText()); 
  768.   displayMenu.entryTick(6,choices.getNoType3Fonts()); 
  769.   displayMenu.entryTick(7,choices.getNoDrawings()); 
  770.   return CLAIM;
  771. }
  772.  
  773. //*************************************************************************
  774.  
  775. Claim DocView::miscMenuATBS(GuiToolboxEvent&,const GuiIdBlock&)
  776. {
  777.   GuiMenu menu("miscMenu");
  778.   menu.entryFade(3,!document->getPDFDoc().okToPrint()); 
  779.   return CLAIM;
  780. }
  781.  
  782. //*************************************************************************
  783.  
  784. Claim DocView::saveMenuATBS(GuiToolboxEvent&,const GuiIdBlock&)
  785. {
  786.   GuiMenu menu("saveMenu");
  787.   menu.entryFade(1,!document->getPDFDoc().okToCopy()); 
  788.   menu.entryFade(3,!document->getPDFDoc().okToCopy()); 
  789.   menu.entryFade(6,!document->getPDFDoc().okToPrint()); 
  790.   menu.entryFade(2,!document->getPDFDoc().okToPrint()); 
  791.   menu.entryFade(4,!document->getPDFDoc().okToCopy()); 
  792.   menu.entryFade(5,!document->getPDFDoc().okToCopy()); 
  793.   return CLAIM;
  794. }
  795.  
  796. //*************************************************************************
  797.  
  798. Claim DocView::highlightLinks(GuiToolboxEvent&,const GuiIdBlock&)
  799. {
  800.   choices.setHighlightLinks(!choices.getHighlightLinks());
  801.   displayMenu.entryTick(2,choices.getHighlightLinks()); 
  802.   showPage();
  803.   return CLAIM;
  804. }
  805.  
  806. //*************************************************************************
  807.  
  808. Claim DocView::setNoImages(GuiToolboxEvent&,const GuiIdBlock&)
  809. {
  810.   choices.setNoImages(!choices.getNoImages());
  811.   displayMenu.entryTick(3,choices.getNoImages()); 
  812.   showPage();
  813.   return CLAIM;
  814. }
  815.  
  816. //*************************************************************************
  817.  
  818. Claim DocView::setNoText(GuiToolboxEvent&,const GuiIdBlock&)
  819. {
  820.   choices.setNoText(!choices.getNoText());
  821.   displayMenu.entryTick(5,choices.getNoText()); 
  822.   showPage();
  823.   return CLAIM;
  824. }
  825.  
  826. //*************************************************************************
  827.  
  828. Claim DocView::setNoType3Fonts(GuiToolboxEvent&,const GuiIdBlock&)
  829. {
  830.   choices.setNoType3Fonts(!choices.getNoType3Fonts());
  831.   displayMenu.entryTick(6,choices.getNoType3Fonts()); 
  832.   showPage();
  833.   return CLAIM;
  834. }
  835.  
  836. //*************************************************************************
  837.  
  838. Claim DocView::setNoDrawings(GuiToolboxEvent&,const GuiIdBlock&)
  839. {
  840.   choices.setNoDrawings(!choices.getNoDrawings());
  841.   displayMenu.entryTick(7,choices.getNoDrawings()); 
  842.   showPage();
  843.   return CLAIM;
  844. }
  845.  
  846. //*************************************************************************
  847.  
  848. Claim DocView::fileInfoATBS(GuiToolboxEvent&,const GuiIdBlock&)
  849. {
  850.   FileInfo_ATBS(document->getFileInfoData());
  851.   return CLAIM;
  852. }
  853.  
  854. //*************************************************************************
  855.  
  856. Claim DocView::scaleView(GuiToolboxEvent& ev,const GuiIdBlock&)
  857. {
  858.   GuiScale::ApplyFactor& af=(GuiScale::ApplyFactor&)ev;
  859.   if (choices.getScale()!=af.factor)
  860.   {
  861.     choices.setScale(af.factor);
  862.     Scale(Scale());
  863.   }
  864.   return CLAIM;
  865. }
  866.  
  867. //*************************************************************************
  868.  
  869. Claim DocView::scaleUp(GuiToolboxEvent&,const GuiIdBlock&)
  870. {
  871.   int percent = choices.getScale();
  872.   choices.setScale((percent*14142)/10000);
  873.   if (Scale() != percent) Scale(Scale());
  874.   return CLAIM;
  875. }
  876.  
  877. //*************************************************************************
  878.  
  879. Claim DocView::scaleDown(GuiToolboxEvent&,const GuiIdBlock&)
  880. {
  881.   int percent = choices.getScale();
  882.   choices.setScale((percent*7071)/10000);
  883.   if (Scale() != percent) Scale(Scale());
  884.   return CLAIM;
  885. }
  886.  
  887. //*************************************************************************
  888.  
  889. Claim DocView::scale100(GuiToolboxEvent&,const GuiIdBlock&)
  890. {
  891.   int percent = choices.getScale();
  892.   choices.setScale(100);
  893.   if (Scale() != percent) Scale(Scale());
  894.   return CLAIM;
  895. }
  896.  
  897. //*************************************************************************
  898.  
  899. Claim DocView::scaleATBS(GuiToolboxEvent&,const GuiIdBlock& id_block)
  900. {
  901.   GuiScale win(id_block.self.id);
  902.   win.setValue(Scale());
  903.   return CLAIM;
  904. }
  905.  
  906. //*************************************************************************
  907.  
  908. Claim DocView::saveDisplayChoices(GuiToolboxEvent&,const GuiIdBlock&)
  909. {
  910.   choices.save();
  911.   return CLAIM;
  912. }
  913.  
  914. //*************************************************************************
  915.  
  916. Claim DocView::findATBS(GuiToolboxEvent&,const GuiIdBlock&)
  917. {
  918.   find(*this);
  919.   return CLAIM;
  920. }
  921.  
  922. //*************************************************************************
  923.  
  924. bool makeDocView(Document* document,const DocViewChoices& choices,int page,int logicalPageOffset)
  925. {
  926.   if (!document) return 0;  
  927.   DocView* view =  new DocView(*document,choices,page,logicalPageOffset);
  928.   return view!=0;
  929. }
  930.  
  931.